/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package model.creature.plant;

import java.awt.Image;
import model.game.GameInterface;
import model.item.Item;
import model.map.cell.PlantableCell;

/**
 * A specialization of Plant that can be used as a base instead of Plant
 *
 * Provides some default characteristics of Plants
 *
 * Plant has two phases : Seed, Mature. It can only be stepped while it's seed.
 *
 * Plant has HP, reach 0 and the plant "disappears"
 *
 * Plant can be upgraded.
 */
public abstract class DefaultPlant extends Plant {

  /**
   * True iff plant is seed (so, if false, plant is mature)
   */
  protected boolean is_seed_;

  /**
   * Plant's happiness after each harvest
   */
  protected int happiness_;

  /**
   * Plant's overall age
   */
  protected int age_;

  /**
   * What's the level of this plant?
   */
  protected int level_;

  /**
   * How much is this plant's Maximum HP
   */
  protected int max_hp_;

  /**
   * How much is this plant's current HP
   */
  protected int hp_;

  /**
   * Constructor
   */
  public DefaultPlant(GameInterface game, PlantableCell cell) {
    super(game, cell);
    is_seed_ = true;
    happiness_ = 0;
    age_ = 0;
    level_ = 0;
    max_hp_ = hp_ = getHPAtCurrentLevel();
  }

  @Override
  public void advanceDay() {
    ++age_;
    PlantableCell mycell = (PlantableCell)getCell();
    if (mycell.isWatered()) {
      if (game_.getGameTime().getCurrentSeason().getName().equals(
              this.getSeason())) {
        ++happiness_;
      }
    }
    if (is_seed_ && happiness_ >= timeToMature()) {
      is_seed_ = false;
      happiness_ = 0;
    }

    if (age_ >= timeToDie()) {
      game_.addImportantMessage(this.getName() + " has died of old age.");
      game_.getCreatures().getPlants().removePlant(this);
    }

    uponAdvanceDay();
  }

  /**
   * Called after advanceDay()
   *
   * May be overridden
   */
  public void uponAdvanceDay() {
    
  }

  @Override
  public void advanceTime() {
    
  }

  @Override
  public boolean isSteppable() {
    return is_seed_;
  }

  @Override
  public void inflictDamage(int amount) {
    hp_ -= amount;
    if (hp_ <= 0) {
      game_.addImportantMessage(this.getName() + " has been killed.");
      game_.getCreatures().getPlants().removePlant(this);
    }
  }

  /**
   * Heals this creature
   */
  @Override
  public void heal(int amount) {
    hp_ = Math.min(hp_ + amount, getMaxHP());
  }

  /**
   * Increments this plant's level and fully restore its hp
   * Assume that player has paid the appropriate amount of money
   */
  @Override
  public void upgrade() {
    assert canUpgrade();
    ++level_;
    hp_ = max_hp_ = getHPAtCurrentLevel();
  }

  /**
   * Returns the level of this plant
   */
  @Override
  public int getLevel() {
    return level_;
  }

      /**
   * Returns the HP of this plant
   */
  public int getHP() {
    return hp_;
  }

  /**
   * Returns the Maximum HP of this plant
   */
  @Override
  public int getMaxHP() {
    return max_hp_;
  }

  /**
   * Retrieves the days required to go from seed to mature
   */
  protected abstract int timeToMature();

  /**
   * Retrieves the days before this plant dies
   */
  protected abstract int timeToDie();

  /**
   * Retrieves the HP of this plant at the given level
   * level can be accessed through getLevel()
   */
  protected abstract int getHPAtCurrentLevel();

  /**
   * Returns true iff plant can be upgraded again now
   * It's current level is given in getLevel()
   */
  @Override
  public abstract boolean canUpgrade();

  /**
   * Retrieves the price to upgrade this plant's level
   * It's current level is given in getLevel()
   * @requires canUpgrade()
   */
  @Override
  public abstract int getUpgradeCost();

  /**
   * Return true iff this plant is ready to be harvested
   */
  @Override
  public abstract boolean isHarvestable();

  /**
   * Harvest this plant and return the fruit
   * @requires this plant is harvestable
   */
  @Override
  public abstract Item harvest();

   /**
   * Returns the image sprite of this plant
   */
  @Override
  public abstract Image getImage();

  /**
   * Returns the name of this plant
   * Primary Key
   */
  @Override
  public abstract String getName();

  /**
   * Returns the season only during this season this plant can grow
   */
  public abstract String getSeason();

  /**
   * Returns the description of this plant
   */
  @Override
  public abstract String getDescription();

}

